home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / src / mo-www.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  24.8 KB  |  1,007 lines

  1. /****************************************************************************
  2.  * NCSA Mosaic for the X Window System                        *
  3.  * Software Development Group                            *
  4.  * National Center for Supercomputing Applications                *
  5.  * University of Illinois at Urbana-Champaign                    *
  6.  * 605 E. Springfield, Champaign IL 61820                    *
  7.  * mosaic@ncsa.uiuc.edu                             *
  8.  *                                        *
  9.  * Copyright (C) 1993, Board of Trustees of the University of Illinois        *
  10.  *                                        *
  11.  * NCSA Mosaic software, both binary and source (hereafter, Software) is    *
  12.  * copyrighted by The Board of Trustees of the University of Illinois        *
  13.  * (UI), and ownership remains with the UI.                    *
  14.  *                                        *
  15.  * The UI grants you (hereafter, Licensee) a license to use the Software    *
  16.  * for academic, research and internal business purposes only, without a    *
  17.  * fee.  Licensee may distribute the binary and source code (if released)   *
  18.  * to third parties provided that the copyright notice and this statement   *
  19.  * appears on all copies and that no charge is associated with such        *
  20.  * copies.                                    *
  21.  *                                        *
  22.  * Licensee may make derivative works.    However, if Licensee distributes    *
  23.  * any derivative work based on or derived from the Software, then        *
  24.  * Licensee will (1) notify NCSA regarding its distribution of the        *
  25.  * derivative work, and (2) clearly notify users that such derivative        *
  26.  * work is a modified version and not the original NCSA Mosaic            *
  27.  * distributed by the UI.                            *
  28.  *                                        *
  29.  * Any Licensee wishing to make commercial use of the Software should        *
  30.  * contact the UI, c/o NCSA, to negotiate an appropriate license for such   *
  31.  * commercial use.  Commercial use includes (1) integration of all or        *
  32.  * part of the source code into a product for sale or license by or on        *
  33.  * behalf of Licensee to third parties, or (2) distribution of the binary   *
  34.  * code or source code to third parties that need it to utilize a        *
  35.  * commercial product sold or licensed by or on behalf of Licensee.        *
  36.  *                                        *
  37.  * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR   *
  38.  * ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED          *
  39.  * WARRANTY.  THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE    *
  40.  * USERS OF THIS SOFTWARE.                            *
  41.  *                                        *
  42.  * By using or copying this Software, Licensee agrees to abide by the        *
  43.  * copyright law and all other applicable laws of the U.S. including, but   *
  44.  * not limited to, export control laws, and the terms of this license.        *
  45.  * UI shall have the right to terminate this license immediately by        *
  46.  * written notice upon Licensee's breach of, or non-compliance with, any    *
  47.  * of its terms.  Licensee may be held legally responsible for any        *
  48.  * copyright infringement that is caused or encouraged by Licensee's        *
  49.  * failure to abide by the terms of this license.                *
  50.  *                                        *
  51.  * Comments and questions are welcome and can be sent to            *
  52.  * mosaic-x@ncsa.uiuc.edu.                            *
  53.  ****************************************************************************/
  54.  
  55. #include "includes.h"
  56. #include "globals.h"
  57. #include "HTML.h"
  58. #include "mosaic.h"
  59. #include <ctype.h>
  60.  
  61. /* Grumble grumble... */
  62. #if defined(__sgi) && !defined(__STDC__)
  63. #define __STDC__
  64. #endif
  65.  
  66. /* libwww includes */
  67. #include "HTUtils.h"
  68. #include "/libwww2/tcp.h"
  69. #include "HTString.h"
  70. #include "HTTCP.h"
  71. #include "HTParse.h"
  72. #include "HTAccess.h"
  73. #include "HText.h"
  74. #include "HTList.h"
  75. #include "HTInit.h"
  76.  
  77.  
  78. #define MO_BUFFER_SIZE 8192
  79.  
  80.  
  81. /* Bare minimum. */
  82. struct _HText {
  83.   char *expandedAddress;
  84.   char *simpleAddress;
  85.  
  86.   /* This is what we should parse and display; it is *not*
  87.      safe to free. */
  88.   char *htmlSrc;
  89.   /* This is what we should free. */
  90.   char *htmlSrcHead;
  91.   int srcalloc;    /* amount of space allocated */
  92.   int srclen;       /* amount of space used */
  93. };
  94.  
  95. /* Mosaic does NOT use either the anchor system or the style sheet
  96.    system of libwww. */
  97.  
  98. HText* HTMainText;            /* Equivalent of main window */
  99.  
  100. char *HTAppName = "Mosaic for Amiga";
  101. extern char *HTAppVersion;
  102.  
  103. int force_dump_to_file;         /* hook to force dumping binary data
  104.                        straight to file named by... */
  105. char *force_dump_filename;        /* this filename. */
  106.  
  107. /* From gui-documents.c */
  108. extern int interrupted;
  109.  
  110. /* From HTTP.c */
  111. extern __far int do_post;
  112. extern __far char *post_content_type;
  113. extern __far char *post_data;
  114.  
  115.  
  116. /****************************************************************************
  117.  * name:    hack_htmlsrc (PRIVATE)
  118.  * purpose: Do really nasty things to a stream of HTML that just got
  119.  *        pulled over from a server.
  120.  * inputs:
  121.  *   - none (global HTMainText is assumed to contain current
  122.  *         HText object)
  123.  * returns:
  124.  *   - HTMainText->htmlSrc (char *)
  125.  * remarks:
  126.  *   This is ugly but it gets the job done.
  127.  *   The job is this:
  128.  *     - Filter out repeated instances of <PLAINTEXT>.
  129.  *     - Discover if <PLAINTEXT> has been improperly applied
  130.  *     to the head of an HTML document (we discover HTML documents
  131.  *     by checking to see if a <TITLE> element is on the next line).
  132.  *     - Same as above but for <HEAD> and <HTML>.
  133.  *   We advance the character pointer HTMainText->htmlSrc by the
  134.  *   appropriate remark to make adjustments, and keep the original
  135.  *   head of the allocated block of text in HTMainText->htmlSrcHead.
  136.  ****************************************************************************/
  137. static char *hack_htmlsrc (void)
  138. {
  139.   if (!HTMainText)
  140.     return NULL;
  141.  
  142.   if (!HTMainText->htmlSrc)
  143.     {
  144.       HTMainText->htmlSrcHead = NULL;
  145.       return NULL;
  146.     }
  147.  
  148.   /* Keep pointer to real head of htmlSrc memory block. */
  149.   HTMainText->htmlSrcHead = HTMainText->htmlSrc;
  150.  
  151.   if (HTMainText->htmlSrc && HTMainText->srclen > 30)
  152.     {
  153.       if (!strncmp (HTMainText->htmlSrc, "<plaintext>", 11) ||
  154.       !strncmp (HTMainText->htmlSrc, "<PLAINTEXT>", 11))
  155.     {
  156.       if (!strncmp (HTMainText->htmlSrc + 11, "<plaintext>", 11) ||
  157.           !strncmp (HTMainText->htmlSrc + 11, "<PLAINTEXT>", 11))
  158.         {
  159.           HTMainText->htmlSrc += 11;
  160.         }
  161.       else if (!strncmp (HTMainText->htmlSrc + 11, "\n<plaintext>", 12) ||
  162.            !strncmp (HTMainText->htmlSrc + 11, "\n<PLAINTEXT>", 12))
  163.         {
  164.           HTMainText->htmlSrc += 12;
  165.         }
  166.       else if (!strncmp (HTMainText->htmlSrc + 11, "\n<title>", 8) ||
  167.            !strncmp (HTMainText->htmlSrc + 11, "\n<TITLE>", 8))
  168.         {
  169.           HTMainText->htmlSrc += 12;
  170.         }
  171.       /* Catch CERN hytelnet gateway, etc. */
  172.       else if (!strncmp (HTMainText->htmlSrc + 11, "\n<HEAD>", 7) ||
  173.            !strncmp (HTMainText->htmlSrc + 11, "\n<head>", 7) ||
  174.            !strncmp (HTMainText->htmlSrc + 11, "\n<HTML>", 7) ||
  175.            !strncmp (HTMainText->htmlSrc + 11, "\n<html>", 7))
  176.         {
  177.           HTMainText->htmlSrc += 12;
  178.         }
  179.     }
  180.       if (!strncmp (HTMainText->htmlSrc,
  181.             "<TITLE>Document</TITLE>\n<PLAINTEXT>", 35))
  182.     {
  183.       if (!strncmp (HTMainText->htmlSrc + 35, "\n<title>", 8) ||
  184.           !strncmp (HTMainText->htmlSrc + 35, "\n<TITLE>", 8))
  185.         {
  186.           HTMainText->htmlSrc += 36;
  187.         }
  188.     }
  189.     }
  190.   return HTMainText->htmlSrc;
  191. }
  192.  
  193.  
  194. /****************************************************************************
  195.  * name:    doit (PRIVATE)
  196.  * purpose: Given a URL, go fetch information.
  197.  * inputs:
  198.  *   - char      *url: The URL to fetch.
  199.  *   - char **texthead: Return pointer for the head of the allocated
  200.  *            text block (which may be different than the
  201.  *            return text intended for display).
  202.  * returns:
  203.  *   The text intended for display (char *).
  204.  ****************************************************************************/
  205. static char *doit (char *url, char **texthead)
  206. {
  207.   char *msg;
  208.   int rv;
  209.   extern __far char *use_this_url_instead;
  210.  
  211.   /* Hmmmmmmm... */
  212.   if (HTMainText)
  213.     {
  214.       free (HTMainText);
  215.       HTMainText = NULL;
  216.     }
  217.  
  218.   rv = HTLoadAbsolute (url);
  219.   if (rv == 1)
  220.     {
  221.       char *txt = hack_htmlsrc ();
  222.       if (HTMainText)
  223.     *texthead = HTMainText->htmlSrcHead;
  224.       else
  225.     *texthead = NULL;
  226.       return txt;
  227.     }
  228.   else if (rv == -1)
  229.     {
  230.       interrupted = 1;
  231.       *texthead = NULL;
  232.       return NULL;
  233.     }
  234.  
  235.   /* Return proper error message if we experienced redirection. */
  236.   if (use_this_url_instead)
  237.     url = use_this_url_instead;
  238.   msg = (char *)malloc ((strlen (url) + 200) * sizeof (char));
  239.   sprintf (msg, "<H1>ERROR</H1> Requested document (URL %s) could not be accessed.<p>The information server either is not accessible or is refusing to serve the document to you.<p>", url);
  240.   *texthead = msg;
  241.   return msg;
  242. }
  243.  
  244.  
  245. /****************************************************************************
  246.  * name:    mo_pull_er_over
  247.  * purpose: Given a URL, pull 'er over.
  248.  * inputs:
  249.  *   - char      *url: The URL to pull over.
  250.  *   - char **texthead: Return pointer to head of allocated block.
  251.  * returns:
  252.  *   Text to display (char *).
  253.  * remarks:
  254.  *
  255.  ****************************************************************************/
  256. char *mo_pull_er_over (char *url, char **texthead)
  257. {
  258.   char *rv;
  259.   extern int binary_transfer;
  260.  
  261.   if (binary_transfer)
  262.     {
  263.       force_dump_to_file = 1;
  264.       force_dump_filename = mo_tmpnam();
  265.     }
  266.   rv = doit (url, texthead);
  267.   if (binary_transfer)
  268.     {
  269.       force_dump_to_file = 0;
  270.       force_dump_filename = NULL;
  271.     }
  272.   return rv;
  273. }
  274.  
  275.  
  276. char *mo_post_pull_er_over (char *url, char *content_type, char *data,
  277.                 char **texthead)
  278. {
  279.   char *rv;
  280.   extern int binary_transfer;
  281.  
  282.   do_post = 1;
  283.   post_content_type = content_type;
  284.   post_data = data;
  285.  
  286.   if (binary_transfer)
  287.     {
  288.       force_dump_to_file = 1;
  289.       force_dump_filename = mo_tmpnam();
  290.     }
  291.   rv = doit (url, texthead);
  292.   if (binary_transfer)
  293.     {
  294.       force_dump_to_file = 0;
  295.       force_dump_filename = NULL;
  296.     }
  297.  
  298.   do_post = 0;
  299.  
  300.   return rv;
  301. }
  302.  
  303.  
  304.  
  305. /****************************************************************************
  306.  * name:    mo_pull_er_over_virgin
  307.  * purpose: Given a URL, pull 'er over in such a way that no format
  308.  *        handling takes place and the data gets dumped in the filename
  309.  *        of the calling routine's choice.
  310.  * inputs:
  311.  *   - char  *url: The URL to pull over.
  312.  *   - char *fnam: Filename in which to dump the received data.
  313.  * returns:
  314.  *   mo_succeed on success; mo_fail otherwise.
  315.  * remarks:
  316.  *   This routine is called when we know there's data out there we
  317.  *   want to get and we know we just want it dumped in a file, no
  318.  *   questions asked, by the WWW library.  Appropriate global flags
  319.  *   are set to make this happen.
  320.  *   This must be made cleaner.
  321.  ****************************************************************************/
  322. mo_status mo_pull_er_over_virgin (char *url, char *fnam)
  323. {
  324.   int rv;
  325.  
  326.   /* Force dump to file. */
  327.   force_dump_to_file = 1;
  328.   force_dump_filename = fnam;
  329.  
  330.   rv = HTLoadAbsolute (url);
  331.   if (rv == 1)
  332.     {
  333.       force_dump_to_file = 0;
  334.       return mo_succeed;
  335.     }
  336.   else if (rv == -1)
  337.     {
  338.       force_dump_to_file = 0;
  339.       interrupted = 1;
  340.       return mo_fail;
  341.     }
  342.   else
  343.     {
  344.       force_dump_to_file = 0;
  345.       return mo_fail;
  346.     }
  347. }
  348.  
  349.  
  350. mo_status mo_re_init_formats (void)
  351. {
  352.   HTReInit ();
  353.   return mo_succeed;
  354. }
  355.  
  356. /* ------------------------------------------------------------------------ */
  357.  
  358. HText *HText_new (void)
  359. {
  360.   HText *htObj = (HText *)malloc (sizeof (HText));
  361.  
  362.   htObj->expandedAddress = NULL;
  363.   htObj->simpleAddress = NULL;
  364.   htObj->htmlSrc = NULL;
  365.   htObj->htmlSrcHead = NULL;
  366.   htObj->srcalloc = 0;
  367.   htObj->srclen = 0;
  368.  
  369.   /* Free the struct but not the text, as it will be handled
  370.      by Mosaic proper -- apparently. */
  371.   if (HTMainText)
  372.     free (HTMainText);
  373.  
  374.   HTMainText = htObj;
  375.  
  376.   return htObj;
  377. }
  378.  
  379. void HText_free (HText *self)
  380. {
  381.   if (self)
  382.     {
  383.       if (self->htmlSrcHead)
  384.     free (self->htmlSrcHead);
  385.       free (self);
  386.     }
  387.   return;
  388. }
  389.  
  390. void HText_beginAppend (HText *text)
  391. {
  392.   HTMainText = text;
  393.   return;
  394. }
  395.  
  396. void HText_endAppend (HText *text)
  397. {
  398.   if (text)
  399.     {
  400.       HText_appendCharacter (text, '\0');
  401.     }
  402.   HTMainText = text;
  403.   return;
  404. }
  405.  
  406. void HText_doAbort (HText *self)
  407. {
  408.   /* Clean up -- we want to free htmlSrc here because htmlSrcHead
  409.      doesn't get assigned until hack_htmlsrc, and by the time we
  410.      reach that, this should never be called. */
  411.   if (self)
  412.     {
  413.       if (self->htmlSrc)
  414.     free (self->htmlSrc);
  415.       self->htmlSrc = NULL;
  416.       self->htmlSrcHead = NULL;
  417.       self->srcalloc = 0;
  418.       self->srclen = 0;
  419.     }
  420.   return;
  421. }
  422.  
  423. void HText_clearOutForNewContents (HText *self)
  424. {
  425.   if (self)
  426.     {
  427.       if (self->htmlSrc)
  428.     free (self->htmlSrc);
  429.       self->htmlSrc = NULL;
  430.       self->htmlSrcHead = NULL;
  431.       self->srcalloc = 0;
  432.       self->srclen = 0;
  433.     }
  434.   return;
  435. }
  436.  
  437. static void new_chunk (HText *text)
  438. {
  439.   if (text->srcalloc == 0)
  440.     {
  441.       text->htmlSrc = (char *)malloc (MO_BUFFER_SIZE);
  442.       text->htmlSrc[0] = '\0';
  443.     }
  444.   else
  445.     {
  446.       text->htmlSrc = (char *)realloc
  447.     (text->htmlSrc, text->srcalloc + MO_BUFFER_SIZE);
  448.     }
  449.  
  450.   text->srcalloc += MO_BUFFER_SIZE;
  451.  
  452.   return;
  453. }
  454.  
  455. void HText_appendCharacter (HText *text, char ch)
  456. {
  457.   if (text->srcalloc < text->srclen + 1)
  458.     new_chunk (text);
  459.  
  460.   text->htmlSrc[text->srclen++] = ch;
  461.  
  462.   return;
  463. }
  464.  
  465. void HText_appendText (HText *text, char *str)
  466. {
  467.   int len;
  468.  
  469.   if (!str)
  470.     return;
  471.  
  472.   len = strlen (str);
  473.  
  474.   while (text->srcalloc < text->srclen + len + 1)
  475.     new_chunk (text);
  476.  
  477.   bcopy (str, (text->htmlSrc + text->srclen), len);
  478.  
  479.   text->srclen += len;
  480.   text->htmlSrc[text->srclen] = '\0';
  481.  
  482.   return;
  483. }
  484.  
  485. void HText_appendBlock (HText *text, char *data, int len)
  486. {
  487.   if (!data)
  488.     return;
  489.  
  490.   while (text->srcalloc < text->srclen + len + 1)
  491.     new_chunk (text);
  492.  
  493.   bcopy (data, (text->htmlSrc + text->srclen), len);
  494.  
  495.   text->srclen += len;
  496.   text->htmlSrc[text->srclen] = '\0';
  497.  
  498.   return;
  499. }
  500.  
  501. void HText_appendParagraph (HText *text)
  502. {
  503.   /* Boy, talk about a misnamed function. */
  504.   char *str = " <p> \n";
  505.  
  506.   HText_appendText (text, str);
  507.  
  508.   return;
  509. }
  510.  
  511. void HText_beginAnchor (HText *text, char *anc)
  512. {
  513.   HText_appendText (text, "<A HREF=\"");
  514.   HText_appendText (text, anc);
  515.   HText_appendText (text, "\">");
  516.   return;
  517. }
  518.  
  519. void HText_endAnchor (HText * text)
  520. {
  521.   HText_appendText (text, "</A>");
  522.   return;
  523. }
  524.  
  525. void HText_dump (HText *me)
  526. {
  527.   return;
  528. }
  529.  
  530. char *HText_getText (HText *me)
  531. {
  532.   if (me)
  533.     return me->htmlSrc;
  534.   else
  535.     return NULL;
  536. }
  537.  
  538. char **HText_getPtrToText (HText *me)
  539. {
  540.   if (me)
  541.     return &(me->htmlSrc);
  542.   else
  543.     return NULL;
  544. }
  545.  
  546. int HText_getTextLength (HText *me)
  547. {
  548.   if (me)
  549.     return me->srclen;
  550.   else
  551.     return NULL;
  552. }
  553.  
  554. BOOL HText_select (HText *text)
  555. {
  556.   return FALSE;
  557. }
  558.  
  559.  
  560.  
  561. /****************************************************************************
  562.  * name:    mo_url_canonicalize
  563.  * purpose: Turn a URL into its canonical form, based on the previous
  564.  *        URL in this context (if appropriate).
  565.  *        INTERNAL ANCHORS ARE STRIPPED OFF.
  566.  * inputs:
  567.  *   - char    *url: URL to canonicalize.
  568.  *   - char *oldurl: The previous URL in this context.
  569.  * returns:
  570.  *   The canonical representation of the URL.
  571.  * remarks:
  572.  *   All we do is call HTParse.
  573.  ****************************************************************************/
  574. char *mo_url_canonicalize (char *url, char *oldurl)
  575. {
  576.   /* We LOSE anchor information. */
  577.   return HTParse (url, oldurl,
  578.           PARSE_ACCESS | PARSE_HOST | PARSE_PATH |
  579.           PARSE_PUNCTUATION);
  580. }
  581.  
  582.  
  583. /****************************************************************************
  584.  * name:    mo_url_canonicalize_keep_anchor
  585.  * purpose: Turn a URL into its canonical form, based on the previous
  586.  *        URL in this context (if appropriate).
  587.  *        INTERNAL ANCHORS ARE *NOT* STRIPPED OFF.
  588.  * inputs:
  589.  *   - char    *url: URL to canonicalize.
  590.  *   - char *oldurl: The previous URL in this context.
  591.  * returns:
  592.  *   The canonical representation of the URL.
  593.  * remarks:
  594.  *   All we do is call HTParse.
  595.  ****************************************************************************/
  596. char *mo_url_canonicalize_keep_anchor (char *url, char *oldurl)
  597. {
  598.   char *rv;
  599.   /* We KEEP anchor information already present in url,
  600.      but NOT in oldurl. */
  601.   oldurl = HTParse (oldurl, "", PARSE_ACCESS | PARSE_HOST | PARSE_PATH |
  602.             PARSE_PUNCTUATION);
  603.   rv = HTParse (url, oldurl,
  604.         PARSE_ACCESS | PARSE_HOST | PARSE_PATH |
  605.         PARSE_PUNCTUATION | PARSE_ANCHOR);
  606.   /* We made a new copy of oldurl, so free the new copy. */
  607.   free (oldurl);
  608.   return rv;
  609. }
  610.  
  611.  
  612. /****************************************************************************
  613.  * name:    mo_url_to_unique_document
  614.  * purpose: Given a URL that may or may not contain an internal anchor,
  615.  *        return a form that corresponds to a unique document -- i.e.,
  616.  *        a URL that has annotations different than all other
  617.  *        URL's, etc.  Generally this will be the URL without the
  618.  *        target anchor, except for automatically generated representations
  619.  *        of internal parts of HDF files.
  620.  * inputs:
  621.  *   - char *url: The URL.
  622.  * returns:
  623.  *   URL corresponding to a unique document.
  624.  * remarks:
  625.  *
  626.  ****************************************************************************/
  627. char *mo_url_to_unique_document (char *url)
  628. {
  629.   char *target = mo_url_extract_anchor (url), *rv;
  630.  
  631.   if (target && !strncmp (target, "hdfref;", 7))
  632.     rv = strdup (url);
  633.   else
  634.     rv = mo_url_canonicalize (url, "");
  635.  
  636.   if (target)
  637.     free (target);
  638.  
  639.   return rv;
  640. }
  641.  
  642.  
  643. /****************************************************************************
  644.  * name:    mo_url_extract_anchor
  645.  * purpose: Given a URL (presumably in canonical form), extract
  646.  *        the internal anchor, if any.
  647.  * inputs:
  648.  *   - char *url: URL to use.
  649.  * returns:
  650.  *   Internal anchor, if one exists in the URL; else NULL.
  651.  * remarks:
  652.  *
  653.  ****************************************************************************/
  654. char *mo_url_extract_anchor (char *url)
  655. {
  656.   return HTParse (url, "", PARSE_ANCHOR);
  657. }
  658.  
  659.  
  660. /****************************************************************************
  661.  * name:    mo_url_extract_access
  662.  * purpose: Given a URL (presumably in canonical form), extract
  663.  *        the access method, if any.
  664.  * inputs:
  665.  *   - char *url: URL to use.
  666.  * returns:
  667.  *   Access method, if one exists in the URL; else NULL.
  668.  * remarks:
  669.  *
  670.  ****************************************************************************/
  671. char *mo_url_extract_access (char *url, char *oldurl)
  672. {
  673.   return HTParse (url, oldurl, PARSE_ACCESS);
  674. }
  675.  
  676.  
  677.  
  678. char *mo_url_canonicalize_local (char *url)
  679. {
  680.   char *cwd = getcwd (NULL, 128);
  681.   char *tmp;
  682.  
  683.   if (!url)
  684.     return NULL;
  685.  
  686.   tmp = (char *)malloc ((strlen (url) +
  687.              strlen (cwd) + 32));
  688.   if (url[0] == '/')
  689.     sprintf (tmp, "file://localhost%s\0",
  690.          url);
  691.   else
  692.      /* file always returned relative to a volume on the amiga */
  693.      sprintf (tmp, "file://localhost/%s/%s\0",cwd,url);
  694.  
  695.   free (cwd);
  696.  
  697.   return tmp;
  698. }
  699.  
  700.  
  701. /****************************************************************************
  702.  * name:    mo_tmpnam
  703.  * purpose: Make a temporary, unique filename.
  704.  * inputs:
  705.  *   none
  706.  * returns:
  707.  *   The new temporary filename.
  708.  * remarks:
  709.  *   We call tmpnam() to get the actual filename, and use the value
  710.  *   of Rdata.tmp_directory, if any, for the directory.
  711.  ****************************************************************************/
  712. #ifndef L_tmpnam
  713. #define L_tmpnam 32
  714. #endif
  715. char *mo_tmpnam (void)
  716. {
  717.   char *tmp = (char *)malloc (sizeof (char) * L_tmpnam);
  718.   char c;
  719.   tmpnam (tmp);
  720.  
  721.   if (!Rdata.tmp_directory)
  722.     {
  723.       /* Fast path. */
  724.       return tmp;
  725.     }
  726.   else
  727.     {
  728.       /* OK, reconstruct to go in the directory of our choice. */
  729.       char *oldtmp = tmp;
  730.       int i;
  731.  
  732.       /* Start at the back and work our way forward. */
  733.       for (i = strlen(oldtmp)-1; i >= 0; i--)
  734.     {
  735.       if (((c = oldtmp[i]) == '/') || (c == ':'))
  736.         goto found_it;
  737.     }
  738.  
  739.       /* No luck, just punt. */
  740.       return tmp;
  741.  
  742.     found_it:
  743.       tmp = (char *)malloc (sizeof (char) * (strlen (Rdata.tmp_directory) +
  744.                          strlen (&(oldtmp[i])) + 8));
  745.       c = Rdata.tmp_directory[strlen(Rdata.tmp_directory)-1];
  746.       if ((c == '/') || (c == ':'))
  747.     {
  748.       /* Trailing slash in tmp_directory spec. */
  749.       sprintf (tmp, "%s%s", Rdata.tmp_directory, &(oldtmp[i])+1);
  750.     }
  751.       else
  752.     {
  753.       /* No trailing slash. */
  754.       sprintf (tmp, "%s/%s", Rdata.tmp_directory, &(oldtmp[i]));
  755.     }
  756.  
  757.       free (oldtmp);
  758.       return tmp;
  759.     }
  760. }
  761.  
  762.  
  763. /* ------------------------------ dumb stuff ------------------------------ */
  764.  
  765. /* Feedback from the library. */
  766. void application_user_feedback (char *str)
  767. {
  768.   MUI_Request(App, WI_Main, 0, "Amiga Mosaic: Application Feedback", "OK", str,
  769.           TAG_END);
  770. }
  771.  
  772. static long paswd=0;
  773.  
  774. char *prompt_for_string (char *questionstr)
  775. {
  776. /*---*/
  777.   extern mo_window *current_win;
  778.   char *str;
  779.   ULONG signal;
  780.   int done=0;
  781.   Object *w, *s, *ok, *cancel;
  782.   enum { RET_OK = 777, RET_CANCEL };
  783.  
  784.     w = WindowObject,
  785.         MUIA_Window_Title, "String Request",
  786.         MUIA_Window_RefWindow, current_win->view,
  787.         MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  788.         MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  789.         MUIA_Window_Width, 400,
  790.         WindowContents, VGroup,
  791.             Child, VGroup,
  792.                 Child, TextObject,MUIA_Text_Contents,questionstr, End,
  793.                 Child, s = StringObject, StringFrame,
  794.                             MUIA_String_Secret,paswd,
  795.                         MUIA_String_MaxLen, 512, End,
  796.                 End,
  797.             Child, HGroup,
  798.                 Child, ok = KeyButton("OK",'o'),
  799.                 Child, cancel = KeyButton("Cancel",'c'),
  800.             End,
  801.         End,
  802.     End;
  803.  
  804.   DoMethod(App, OM_ADDMEMBER, w);
  805.  
  806.   DoMethod(w, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App, 2,
  807.        MUIM_Application_ReturnID, RET_CANCEL);
  808.   DoMethod(ok, MUIM_Notify, MUIA_Pressed, FALSE, App, 2,
  809.        MUIM_Application_ReturnID, RET_OK);
  810.   DoMethod(cancel, MUIM_Notify, MUIA_Pressed, FALSE, App, 2,
  811.        MUIM_Application_ReturnID, RET_CANCEL);
  812.   DoMethod(s, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime,
  813.        App, 2, MUIM_Application_ReturnID, RET_OK);
  814.  
  815.   set(w, MUIA_Window_Open, TRUE);
  816.  
  817.   while (done == 0) {
  818.  
  819.     switch (DoMethod(App, MUIM_Application_Input, &signal)) {
  820.     case RET_OK:
  821.       get(s, MUIA_String_Contents, &str);
  822.       done = 1;
  823.       break;
  824.     case RET_CANCEL:
  825.       str = NULL;
  826.       done = 1;
  827.       break;
  828.     }
  829.     if (signal) {
  830.       Wait(signal);
  831.     }
  832.   }
  833.  
  834.   set(w, MUIA_Window_Open, FALSE);
  835.   DoMethod(App, OM_REMMEMBER, w);
  836.   MUI_DisposeObject(w);
  837.  
  838.   return str;
  839. }
  840.  
  841. char *prompt_for_password (char *questionstr)
  842. {
  843.     char *res;
  844.     paswd=TRUE; /* Quite dirty, but it works! */
  845.     res = prompt_for_string(questionstr);
  846.     paswd=FALSE;
  847.     return res;
  848. }
  849.  
  850. int prompt_for_yes_or_no (char *questionstr)
  851. {
  852. #ifndef _AMIGA
  853.   extern XtAppContext app_context;
  854.   extern mo_window *current_win;
  855.  
  856.   return XmxModalYesOrNo (current_win->base, app_context,
  857.               questionstr, "Yes", "No");
  858. #endif
  859.   return 0;
  860. }
  861.  
  862. char *mo_get_html_return (char **texthead)
  863. {
  864.   char *txt = hack_htmlsrc ();
  865.   *texthead = HTMainText->htmlSrcHead;
  866.   return txt;
  867. }
  868.  
  869. /* Simply loop through a string and convert all newlines to spaces. */
  870. char *mo_convert_newlines_to_spaces (char *str)
  871. {
  872.   int i;
  873.  
  874.   if (!str)
  875.     return NULL;
  876.  
  877.   for (i = 0; i < strlen (str); i++)
  878.     if (str[i] == '\n')
  879.       str[i] = ' ';
  880.  
  881.   return str;
  882. }
  883.  
  884. /* ---------------------------- escaping code ----------------------------- */
  885.  
  886. static unsigned char isAcceptable[96] =
  887. /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
  888. {    0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,    /* 2x    !"#$%&'()*+,-./  */
  889.      1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,    /* 3x  0123456789:;<=>?  */
  890.      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    /* 4x  @ABCDEFGHIJKLMNO  */
  891.      1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,    /* 5x  PQRSTUVWXYZ[\]^_  */
  892.      0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    /* 6x  `abcdefghijklmno  */
  893.      1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; /* 7x  pqrstuvwxyz{\}~    DEL */
  894.  
  895. #define MO_HEX(i) (i < 10 ? '0'+i : 'A'+ i - 10)
  896.  
  897. /* The string returned from here, if any, can be free'd by caller. */
  898. char *mo_escape_part (char *part)
  899. {
  900.   char *q /* , *u */;
  901.   char *p /* , *s, *e */;        /* Pointers into keywords */
  902.   char *escaped;
  903.  
  904.   if (!part)
  905.     return NULL;
  906.  
  907.   escaped = (char *)malloc (strlen (part) * 3 + 1);
  908.  
  909.   for (q = escaped, p = part; *p != '\0'; p++)
  910.     {
  911.       /*
  912.        * This makes sure that values 128 and over don't get
  913.        * converted to negative values.
  914.        */
  915.       int c = (int)((unsigned char)(*p));
  916.       if (*p == ' ')
  917.     {
  918.       *q++ = '+';
  919.     }
  920.       else if (c >= 32 && c <= 127 && isAcceptable[c-32])
  921.     {
  922.       *q++ = *p;
  923.     }
  924.       else
  925.     {
  926.       *q++ = '%';
  927.       *q++ = MO_HEX(c / 16);
  928.       *q++ = MO_HEX(c % 16);
  929.     }
  930.     }
  931.  
  932.   *q=0;
  933.  
  934.   return escaped;
  935. }
  936.  
  937.  
  938. static char mo_from_hex (char c)
  939. {
  940.   return (char)((c >= '0' && c <= '9') ? (c - '0') :
  941.       ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) :
  942.        (c - 'a' + 10)));
  943. }
  944.  
  945. char *mo_unescape_part (char *str)
  946. {
  947.   char *p = str, *q = str;
  948.  
  949.   while (*p)
  950.     {
  951.       /* Plus's turn back into spaces. */
  952.       if (*p == '+')
  953.     {
  954.       *q++ = ' ';
  955.       p++;
  956.     }
  957.       else if (*p == '%')
  958.     {
  959.       p++;
  960.       if (*p)
  961.         *q = mo_from_hex(*p++) * 16;
  962.       if (*p)
  963.         *q += mo_from_hex(*p++);
  964.       q++;
  965.     }
  966.       else
  967.     {
  968.       *q++ = *p++;
  969.     }
  970.     }
  971.  
  972.   *q++ = 0;
  973.   return str;
  974. }
  975.  
  976.  
  977. #ifdef TIMING
  978. /* ----------------------------- Timing stuff ----------------------------- */
  979.  
  980. #include <sys/types.h>
  981. #include <sys/times.h>
  982. #include <sys/param.h>
  983.  
  984. /* Time globals. */
  985. static struct tms tbuf;
  986. static int gtime;
  987.  
  988. void StartClock (void)
  989. {
  990.   gtime = times (&tbuf);
  991.  
  992.   return;
  993. }
  994.  
  995. void StopClock ()
  996. {
  997.   int donetime;
  998.  
  999.   donetime = times(&tbuf);
  1000.  
  1001.   fprintf (stderr, "Elapsed time %d\n", donetime - gtime);
  1002.  
  1003.   return;
  1004. }
  1005. #endif
  1006.  
  1007.